package com.ikas.ai.server.mock;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ikas.ai.server.module.instance.model.DorisWorkInstanceStepDetail;
import com.ikas.ai.server.module.instance.service.DorisWorkFlowInstanceService;
import com.ikas.ai.server.module.instance.service.DorisWorkInstanceStepDetailService;
import com.ikas.ai.server.module.instance.service.DorisWorkInstanceStepService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class MockIQR {

    @Autowired
    DorisWorkInstanceStepService dorisWorkInstanceStepService;
    @Autowired
    DorisWorkInstanceStepDetailService dorisWorkInstanceStepDetailService;
    @Autowired
    DorisWorkFlowInstanceService dorisWorkFlowInstanceService;

    @Test
    public void testIQR(){
        DorisWorkInstanceStepDetail byId = dorisWorkInstanceStepDetailService.getById(1726540559711969283L);
        checkAssessAndUnitDeterioration(byId);
    }

    /**
     * 检查是否符合劣化预警以及状态评价的触发条件
     *
     * @param detail
     */
    private void checkAssessAndUnitDeterioration(DorisWorkInstanceStepDetail detail) {
        List<DorisWorkInstanceStepDetail> list;
        LambdaQueryWrapper<DorisWorkInstanceStepDetail> timeWrapper = new LambdaQueryWrapper<DorisWorkInstanceStepDetail>()
                .eq(DorisWorkInstanceStepDetail::getDetailId, detail.getDetailId())
                .gt(DorisWorkInstanceStepDetail::getCostTime,0)
                .gt(DorisWorkInstanceStepDetail::getCreateTime, getStartOfDayTimestampAgo(30))
                .lt(DorisWorkInstanceStepDetail::getCreateTime, getStartOfDayTimestampAfter(1));
        LambdaQueryWrapper<DorisWorkInstanceStepDetail> wrapper = new LambdaQueryWrapper<DorisWorkInstanceStepDetail>()
                .eq(DorisWorkInstanceStepDetail::getDetailId, detail.getDetailId());
        int countWithTime = dorisWorkInstanceStepDetailService.count(timeWrapper);
        if (countWithTime > 100) {
            list = dorisWorkInstanceStepDetailService.list(
                    wrapper.last("limit 100")
            );
        } else {
            list = dorisWorkInstanceStepDetailService.list(timeWrapper);
        }
        if (CollectionUtil.isEmpty(list)) {
            log.info("detailList is null");
            return;
        }
        double[] hisData = list.stream()
                .mapToDouble(ele -> BigDecimal.valueOf(ele.getCostTime()).doubleValue())
                .toArray();
        if (hisData == null || detail.getCostTime() == null || hisData.length == 0) {
            if (hisData == null) {
                log.info("hisData == null");
            }
            else if(detail.getCostTime() == null){
                log.info("detail.getCostTime()==null");
            } else if (hisData.length==0) {
                log.info("hisData.length==0");
            }
            return;
        }
        if (calculateIQRByCommonMath3(hisData, detail.getCostTime().doubleValue())) {
            log.info("MATCH");
        }
    }

    private boolean calculateIQRByCommonMath3(double[] hisData, double data) {
        DescriptiveStatistics stats = new DescriptiveStatistics(hisData);
        double q1 = stats.getPercentile(25); // 第一四分位数（Q1）
        double q3 = stats.getPercentile(75); // 第三四分位数（Q3）
        double iqr = q3 - q1; // 四分位数范围（IQR）
        // 计算上须和下须
//        double lowerWhisker = q1 - 1.5 * iqr;
        double upperWhisker = q3 + 1.5 * iqr;
        log.info("上须值计算：hisData:{},data:{},q3:{},iqr:{},upperWhisker:{},{}", hisData, data,q3, iqr,upperWhisker, data > upperWhisker);
        return data > upperWhisker;
    }

    /**
     * 获取0点的时间戳
     *
     * @param daysAgo
     * @return
     */
    public static Date getStartOfDayTimestampAgo(int daysAgo) {
        LocalDateTime dateTime = LocalDateTime.now().minusDays(daysAgo);
        LocalDateTime startOfDay = dateTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
        return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }
    public static Date getStartOfDayTimestampAfter(int dayAfter) {
        LocalDateTime dateTime = LocalDateTime.now().plusDays(dayAfter);
        LocalDateTime startOfDay = dateTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
        return Date.from( startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }
}
